home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
152_01
/
grep.c
< prev
next >
Wrap
Text File
|
1985-03-09
|
18KB
|
669 lines
/*
HEADER: CUG152.08;
TITLE: Source code for Unix-like GREP command
to find strings in files;
DATE: 09/04/85;
DESCRIPTION:
"A program to find strings in a file. The program
uses the GREP command like UNIX."
KEYWORDS: find, string, file;
FILENAME: GREP.C;
WARNINGS:
"Upper and lower case are always ignored.
Blank lines always fail to match.
The authors claim copyrights and authorize non-commercial
use only.
The typist of this heading does not have equipment to run
this program and prepared this header from comments
within the source code or companion files."
AUTHORS: David N. Smith
Digital Equipment Corp.(DECUS);
COMPILERS: CI/C86;
REFERENCES:
AUTHERS: " ";
TITLE: " ";
CITATION: " ";
ENDREF
*/
/*
*
*
* The information in this document is subject to change
* without notice and should not be construed as a commitment
* by Digital Equipment Corporation or by DECUS.
*
* Neither Digital Equipment Corporation, DECUS, nor the authors
* assume any responsibility for the use or reliability of this
* document or the described software.
*
* Copyright (C) 1980, DECUS
*
*
* General permission to copy or modify, but not for profit, is
* hereby granted, provided that the above copyright notice is
* included and reference made to the fact that reproduction
* privileges were granted by DECUS.
*
*/
#include "stdio.h"
/*
* grep.
*
* Runs on the Decus compiler or on vms.
* Converted for BDS compiler (under CP/M-80), 20-Jan-83, by Chris Kern.
*
* Converted to IBM PC with CI-C86 C Compiler June 1983 by David N. Smith
*
* On vms, define as:
*
* grep :== "$disk:[account]grep" (native)
* grep :== "$disk:[account]grep grep" (Decus)
*
* See below for more information.
*
*/
char *documentation[] = {
"grep searches a file for a given pattern. Execute by",
" grep [flags] regular_expression file_list",
"",
"Flags are single characters preceeded by '-':",
" -c Only a count of matching lines is printed",
" -f Print file name for matching lines switch, see below",
" -n Each line is preceeded by its line number",
" -v Only print non-matching lines",
"",
"The file_list is a list of files (wildcards are acceptable on RSX modes).",
"",
"The file name is normally printed if there is a file given.",
"The -f flag reverses this action (print name no file, not if more).",
"",
0 };
char *patdoc[] = {
"The regular_expression defines the pattern to search for. Upper- and",
"lower-case are always ignored. Blank lines never match. The expression",
"should be quoted to prevent file-name translation.",
"x An ordinary character (not mentioned below) matches that character.",
"'\\' The backslash quotes any character. \"\\$\" matches a dollar-sign.",
"'^' A circumflex at the beginning of an expression matches the",
" beginning of a line.",
"'$' A dollar-sign at the end of an expression matches the end of a line.",
"'.' A period matches any character except \"new-line\".",
"':a' A colon matches a class of characters described by the following",
"':d' character. \":a\" matches any alphabetic, \":d\" matches digits,",
"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
"': ' other control characters, such as new-line.",
"'*' An expression followed by an asterisk matches zero or more",
" occurrances of that expression: \"fo*\" matches \"f\", \"fo\"",
" \"foo\", etc.",
"'+' An expression followed by a plus sign matches one or more",
" occurrances of that expression: \"fo+\" matches \"fo\", etc.",
"'-' An expression followed by a minus sign optionally matches",
" the expression.",
"'[]' A string enclosed in square brackets matches any character in",
" that string, but no others. If the first character in the",
" string is a circumflex, the expression matches any character",
" except \"new-line\" and the characters in the string. For",
" example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
" matches \"abc\" but not \"axb\". A range of characters may be",
" specified by two characters separated by \"-\". Note that,",
" [a-z] matches alphabetics, while [z-a] never matches.",
"The concatenation of regular expressions is a regular expression.",
0};
#define LMAX 512
#define PMAX 256
#define CHAR 1
#define BOL 2
#define EOL 3
#define ANY 4
#define CLASS 5
#define NCLASS 6
#define STAR 7
#define PLUS 8
#define MINUS 9
#define ALPHA 10
#define DIGIT 11
#define NALPHA 12
#define PUNCT 13
#define RANGE 14
#define ENDPAT 15
int cflag;
int fflag;
int nflag;
int vflag;
int nfile;
int debug = 0; /* Set for debug code */
char *pp;
#ifndef vms
char file_name[81];
#endif
char lbuf[LMAX];
char pbuf[PMAX];
/*******************************************************/
main(argc, argv)
char *argv[];
{
register char *p;
register int c, i;
int gotpattern;
int gotcha;
FILE *f;
if (argc <= 1)
usage("No arguments");
if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
help(documentation);
help(patdoc);
return;
}
nfile = argc-1;
gotpattern = 0;
for (i=1; i < argc; ++i) {
p = argv[i];
if (*p == '-') {
++p;
while (c = *p++) {
switch(tolower(c)) {
case '?':
help(documentation);
break;
case 'C':
case 'c':
++cflag;
break;
case 'D':
case 'd':
++debug;
break;
case 'F':
case 'f':
++fflag;
break;
case 'n':
case 'N':
++nflag;
break;
case 'v':
case 'V':
++vflag;
break;
default:
usage("Unknown flag");
}
}
argv[i] = 0;
--nfile;
} else if (!gotpattern) {
compile(p);
argv[i] = 0;
++gotpattern;
--nfile;
}
}
if (!gotpattern)
usage("No pattern");
if (nfile == 0)
grep(stdin, 0);
else {
fflag = fflag ^ (nfile > 0);
for (i=1; i < argc; ++i) {
if (p = argv[i]) {
if ((f=fopen(p, "r")) == NULL)
cant(p);
else {
grep(f, p);
fclose(f);
}
}
}
}
}
/*******************************************************/
file(s)
char *s;
{
printf("File %s:\n", s);
}
/*******************************************************/
cant(s)
char *s;
{
fprintf(stderr, "%s: cannot open\n", s);
}
/*******************************************************/
help(hp)
char **hp; /* dns added extra '*' */
/*
* Give good help
*/
{
register char **dp;
for (dp = hp; *dp; dp++)
printf("%s\n", *dp);
}
/*******************************************************/
usage(s)
char *s;
{
fprintf(stderr, "?GREP-E-%s\n", s);
fprintf(stderr,
"Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n");
exit(1);
}
/*******************************************************/
compile(source)
char *source; /* Pattern to compile */
/*
* Compile the pattern into global pbuf[]
*/
{
register char *s; /* Source string pointer */
register char *lp; /* Last pattern pointer */
register int c;